#include "../inc/memPool.h"
using namespace std;

namespace memoryPoolV1 {
MemoryPool::MemoryPool(size_t BlockSize) : BlockSize_(BlockSize) {}

MemoryPool::~MemoryPool() {
    // 删除连续的block
    Slot *cur = firstBlock_;
    while (cur) {
        Slot *next = cur->next;
        operator delete(reinterpret_cast<void *>(cur));
        // void类型不需要调用析构函数 只释放空间
        cur = next;
    }
}

void MemoryPool::init(std::size_t size) {
    assert(size > 0);
    SlotSize_ = size;
    firstBlock_ = nullptr;
    curSlot_ = nullptr;
    freeList_.store(nullptr, std::memory_order_relaxed);
    lastSlot_ = nullptr;
}

void *MemoryPool::allocate() {
    // 优先使用空闲链表中的内存槽
    Slot *slot = popFreeList();

    if (!slot)
        return slot;

    // 空闲链表为空
    lock_guard<mutex> lock(mutexForBlock_);
    if (curSlot_ >= lastSlot_)
        allocateNewBlock(); // 无槽可用，申请新内存
    Slot *res = curSlot_;
    curSlot_ = reinterpret_cast<Slot *>(reinterpret_cast<char *>(curSlot_) + SlotSize_);

    return res;
}

void MemoryPool::deallocate(void *ptr) {
    if (ptr) {
        // 回收内存，头插法插入空闲链表
        // lock_guard<mutex> lock(mutexForFreeList_);
        // reinterpret_cast<Slot *>(ptr)->next = freeList_;
        // freeList_ = reinterpret_cast<Slot *>(ptr);
        Slot *slot = static_cast<Slot *>(ptr);
        pushFreeList(slot);
    }
}

bool MemoryPool::pushFreeList(Slot *slot) {
    while (1) {
        // 获取当前头节点
        Slot *oldHead = freeList_.load(std::memory_order_relaxed);
        slot->next.store(oldHead, memory_order_relaxed);

        if (freeList_.compare_exchange_weak(oldHead, slot, memory_order_release, memory_order_relaxed))
            return true;

        // CAS失败重试
    }
}

Slot *MemoryPool::popFreeList() {
    // 无锁出队列
    while (1) {
        Slot *oldHead = freeList_.load(std::memory_order_relaxed);
        if (!oldHead)
            return nullptr;
        Slot *newHead = nullptr;
        try {
            newHead = oldHead->next.load(memory_order_relaxed);
        } catch (...) {
            continue;
        }
        // 更新
        if (freeList_.compare_exchange_weak(oldHead, newHead, std::memory_order_acquire, memory_order_relaxed))
            return oldHead;
    }
}

void MemoryPool::allocateNewBlock() {
    void *newBlock = operator new(BlockSize_);
    reinterpret_cast<Slot *>(newBlock)->next = firstBlock_;
    firstBlock_ = reinterpret_cast<Slot *>(newBlock); // 头插法

    char *body = reinterpret_cast<char *>(newBlock) + sizeof(Slot *);
    size_t paddingSize = padPointer(body, SlotSize_); // 计算对齐填充多少内存
    curSlot_ = reinterpret_cast<Slot *>(body + paddingSize);

    // 超过该标记位置说明无槽可用了
    lastSlot_ = reinterpret_cast<Slot *>(reinterpret_cast<size_t>(newBlock) + BlockSize_ - SlotSize_ + 1);

    freeList_ = nullptr;
}

// 指针对齐到槽大小的倍数位置
size_t MemoryPool::padPointer(char *p, size_t align) {
    return (align - reinterpret_cast<size_t>(p)) % align; // align是槽大小
}

void HashBucket::initMemoryPool() {
    for (int i = 0; i < MEMORY_POOL_NUM; i++)
        getMemoryPool(i).init((i + 1) * SLOT_BASE_SIZE);
}

// 单例模式
MemoryPool &HashBucket::getMemoryPool(int idx) {
    static MemoryPool memPool[MEMORY_POOL_NUM];
    return memPool[idx];
}

} // namespace memoryPoolV1
